package com.share51.novel.security.interceptor;

import com.share51.novel.common.ResponseUtil;
import com.share51.novel.config.NovelConfig;
import com.share51.novel.security.annotation.HasLogin;
import com.share51.novel.security.annotation.HasReferer;
import com.share51.novel.security.constant.SecurityConstant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.stream.Stream;

/**
 * 安全配置拦截器
 * @author gb
 */
@Component
public class SecurityInterceptor extends HandlerInterceptorAdapter {

    /**
     * 拦截器配置拦截url
     */
    public static final String[] PATH_URL={"/**"};
    /**
     * 不拦截的请求
     */
    public static final String[] EXCLUDE_PATH_URL={"/sys/**"};

    private static final String USER_AGENT_NAME="user-agent";

    private static final String REFERER_NAME="referer";

    @Resource
    private NovelConfig novelConfig;

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        if (handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 防盗链判断
            HasReferer hasReferer = handlerMethod.getMethodAnnotation(HasReferer.class);
            if (hasReferer!=null&&hasReferer.validate()){
                String userAgent="";
                String referer="";
                Enumeration<String> headerNames = request.getHeaderNames();
                while (headerNames.hasMoreElements()){
                    String headerName=headerNames.nextElement();
                    if (USER_AGENT_NAME.equalsIgnoreCase(headerName)){
                        userAgent=request.getHeader(headerName);
                    }
                    if (REFERER_NAME.equalsIgnoreCase(headerName)){
                        referer=request.getHeader(headerName);
                    }
                }
                if (hasReferer.allowSpider()){
                    // 判断是搜索引擎吗
                    String currentUserAgent = Stream.of(SecurityConstant.CONTAIN_ALLOW_USER_AGENT)
                            .filter(userAgent::contains)
                            .findAny()
                            .orElse(null);
                    if (currentUserAgent!=null){
                        return true;
                    }
                }
                if (StringUtils.isBlank(referer)){
                    ResponseUtil.print(response,401,"缺少必要的参数信息");
                    return false;
                }
                String hostName= novelConfig.getHostName();
                if (referer.contains(hostName)){
                    return true;
                }
                ResponseUtil.print(response,401,"缺少必要的参数信息");
                return false;
            }
            // 用户登录校验
            HasLogin hasLogin = handlerMethod.getMethodAnnotation(HasLogin.class);
            if (hasLogin!=null){
                // 判断用户是否登录
                boolean flag = (boolean)request.getSession().getAttribute(SecurityConstant.USER_IS_LOGIN);
                if (!flag){
                    ResponseUtil.print(response,401,"用户未登录");
                    return false;
                }
            }
        }
        return true;
    }
}
